# service/action_item.py
import logging
from abc import ABC, abstractmethod
import pydantic
import sqlalchemy as sa
from fastapi import Request
from fastapi_pagination.ext.databases import paginate

from admin.service.base_service import BaseService
from models import action_item
from schema_base import PageInationResult
from utils.db_operate import generate_query_conditions
from admin.schemas.action_item import ActionItemListIn, ActionItemAddIn, ActionItemEditIn, ActionItemOut

logger = logging.getLogger(__name__)


class IActionItemService(ABC):
    @abstractmethod
    async def list(self, list_in: ActionItemListIn) -> PageInationResult[ActionItemOut]:
        pass

    @abstractmethod
    async def detail(self, id_: int) -> ActionItemOut:
        pass

    @abstractmethod
    async def add(self, add_in: ActionItemAddIn):
        pass

    @abstractmethod
    async def edit(self, edit_in: ActionItemEditIn):
        pass

    @abstractmethod
    async def delete(self, id_: int):
        pass


class ActionItemService(IActionItemService, BaseService):
    tableModel = action_item.ActionItem.__table__

    def __init__(self, request: Request):
        super().__init__(request)

    @classmethod
    async def instance(cls, request: Request):
        return cls(request)

    async def list(self, list_in: ActionItemListIn):
        where = generate_query_conditions(list_in, self.tableModel)
        q = sa.select(self.tableModel).where(*where).select_from(self.tableModel).order_by(
            self.tableModel.c.created_at.desc())
        res = await paginate(self.conn, q)
        return res

    async def detail(self, id_: int):
        model = await self.conn.fetch_one(self.tableModel.select().where(self.tableModel.c.id == id_).limit(1))
        assert model, "不存在"
        return ActionItemOut.from_orm(model)

    async def add(self, add_in: ActionItemAddIn):
        vals = add_in.dict(exclude_none=True)
        vals.setdefault("status", "open")
        await self.conn.execute(self.tableModel.insert().values(vals))

    async def edit(self, edit_in: ActionItemEditIn):
        assert await self.conn.fetch_one(
            self.tableModel.select().where(self.tableModel.c.id == edit_in.id).limit(1)), "不存在"
        vals = edit_in.dict(exclude_none=True)
        vals.pop("id", None)
        await self.conn.execute(self.tableModel.update().where(self.tableModel.c.id == edit_in.id).values(vals))

    async def delete(self, id_: int):
        assert await self.conn.fetch_one(self.tableModel.select().where(self.tableModel.c.id == id_).limit(1)), "不存在"
        await self.conn.execute(self.tableModel.delete().where(self.tableModel.c.id == id_))
